package main

import (
	"crypto/md5"
	"crypto/rand"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"github.com/patrickmn/go-cache"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"time"
)

// 用户/组织登录
func userLogin(login Login, db *gorm.DB, cache *cache.Cache) *Result {
	user, err := getUserDao(login, db)
	if err != nil {
		return &Result{
			Code: 400,
			Data: "登录失败，用户名与组织不匹配",
		}
	} else {
		err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password))
		if err != nil {
			return &Result{
				Code: 400,
				Data: "登录失败，密码错误",
			}
		} else {
			token := getToken()
			err := setToken(cache, token, login, time.Hour)
			if err != nil {
				return &Result{
					Code: 400,
					Data: err.Error(),
				}
			}
			return &Result{
				Code: 200,
				Data: token,
			}
		}
	}
}

// OrganRegister 组织注册
func OrganRegister(organData OrgRegData, db *gorm.DB) *Result {
	if organData.Name == "" || organData.AdminUsername == "" || organData.AdminPassword == "" {
		return &Result{
			Code: 400,
			Data: "数据不能为空!",
		}
	}
	b := md5.Sum([]byte(organData.Name))
	organData.Id = fmt.Sprintf("%x", b[:])
	organ := &Organ{
		organData.Id,
		organData.Name,
		organData.Description,
		organData.AdminUsername,
	}
	password, err := bcrypt.GenerateFromPassword([]byte(organData.AdminPassword), 10)
	if err != nil {
		return &Result{
			Code: 400,
			Data: "格式化密码错误",
		}
	}
	user := &User{
		organData.Id,
		organData.AdminUsername,
		string(password),
	}

	err1 := db.Create(&organ).Error
	if err1 != nil {
		return &Result{
			Code: 400,
			Data: "注册失败，组织名不可用",
		}
	}
	err2 := db.Create(&user).Error
	if err2 != nil {
		db.Delete(&organ)
		return &Result{
			Code: 400,
			Data: "注册失败，组织管理员已存在",
		}
	}
	return &Result{
		Code: 200,
		Data: "注册成功！",
	}
}

// UserRegister 用户注册
func UserRegister(user *User, db *gorm.DB) *Result {
	if user.Username == "" || user.Password == "" {
		return &Result{
			Code: 400,
			Data: "用户名或密码不能为空!",
		}
	}
	password, _ := bcrypt.GenerateFromPassword([]byte(user.Password), 10)
	user.Password = string(password)
	err := db.Create(&user).Error
	if err != nil {
		return &Result{
			Code: 400,
			Data: err.Error(),
		}
	}
	return &Result{
		Code: 200,
		Data: "注册成功！",
	}
}

func getAllOrganImp(db *gorm.DB) *Result {
	organ, err := getAllOrgan(db)
	if err != nil {
		return &Result{
			Code: 400,
			Data: "系统错误",
		}
	} else {
		res, _ := json.Marshal(organ)
		return &Result{
			Code: 200,
			Data: string(res),
		}
	}
}
func getOrganByIdImp(id string, db *gorm.DB) *Result {
	organ, err := getOrganByID(id, db)
	if err != nil {
		return &Result{
			Code: 400,
			Data: "不存在该组织！",
		}
	} else {
		res, _ := json.Marshal(organ)
		return &Result{
			Code: 200,
			Data: string(res),
		}
	}
}

// 生成token内部接口 登录会调用
func getToken() string {
	b := make([]byte, 8)
	rand.Read(b)
	token := sha256.Sum256(b)
	return fmt.Sprintf("%x", token)
}

// 鉴权外部接口
func checkToken(token string, cache *cache.Cache) (Login, bool) {
	l, hasFound := cache.Get("token_" + token)
	if hasFound {
		return l.(Login), hasFound
	} else {
		return Login{}, hasFound
	}
}

// 设置token内部接口
func setToken(cache *cache.Cache, token string, data interface{}, duration time.Duration) error {
	err := cache.Add("token_"+token, data, duration)
	return err
}

func changePassword(password string, login Login, db *gorm.DB, cache *cache.Cache) *Result {
	res := userLogin(login, db, cache)
	if res.Code == 200 {
		enCode, _ := bcrypt.GenerateFromPassword([]byte(password), 10)
		err := db.Model(&User{}).Where("username=?", login.Username).Update("password", string(enCode)).Error
		if err != nil {
			return &Result{
				Code: 400,
				Data: err.Error(),
			}
		} else {
			return &Result{
				Code: 200,
				Data: "修改成功！",
			}
		}
	} else {
		return &Result{
			Code: 400,
			Data: "原密码错误！",
		}
	}
}
